from django_redis import get_redis_connection
from rest_framework import serializers

from goods.models import SKU


class PlaceOrderSerializer(serializers.ModelSerializer):

    count = serializers.IntegerField(label='个数')

    class Meta:
        model = SKU
        fields = ['id','name','price','default_image_url','count']

class PlaceSerializer(serializers.Serializer):

    skus = PlaceOrderSerializer(many=True)
    # max_digits, decimal_places
    # max_digits    最大长度
    # decimal_places  小数点的位数
    # 100.01
    freight = serializers.DecimalField(max_digits=10,decimal_places=2)


from .models import OrderInfo, OrderGoods


class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderInfo
        fields = ('order_id', 'address', 'pay_method')
        read_only_fields = ('order_id',)
        extra_kwargs = {
            'address': {
                'write_only': True,
                'required': True,
            },
            'pay_method': {
                'write_only': True,
                'required': True
            }
        }

    def create(self, validated_data):
        # # 一, 先实现订单信息的保存
        # #     1.1 先接收地址信息
        # address = validated_data['address']
        # #     1.2 接收支付方式
        # pay_method = validated_data['pay_method']
        # #     1.3 接收用户信息
        # user =self.context['request'].user
        # #     1.4 生成订单id
        # # 年月日时分秒+9位用户id信息
        # from django.utils import timezone
        # # Year,年
        # # month,月
        # # day,日
        # # Hour 小时
        # # Minute 分钟
        # # Second 秒
        #
        # order_id = timezone.now().strftime('%Y%m%d%H%M%S') + '%09d'%user.id
        # #     1.5 订单总数量和总价格(先为0)以及运费
        # total_count=0
        # from decimal import Decimal
        # total_amount=Decimal('0')#总价格
        # freight = Decimal('10') #运费
        # #     1.6 根据支付方式决定状态
        # # 如果是 货到付款 则应该是 待发货
        # # 如果是 支付宝  则应该是  待付款
        # # if pay_method == 1:
        # #     status = 2
        # # else:
        # #     status = 1
        #
        # if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
        #     status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        # else:
        #     status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']
        #
        # #     order
        # order = OrderInfo.objects.create(
        #     order_id=order_id,
        #     user=user,
        #     address=address,
        #     total_count=total_count,
        #     total_amount=total_amount,
        #     freight=freight,
        #     pay_method=pay_method,
        #     status=status
        # )
        #
        #
        # pass
        address = validated_data['address']
        pay_method = validated_data['pay_method']
        user = self.context['request'].user
        from django.utils import timezone
        order_id = timezone.now().strftime('%Y%m%d%H%M%S')
        total_count =0
        from decimal import Decimal
        total_amount = Decimal('0')
        freight = Decimal('10')
        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        from django.db import transaction
        with transaction.atomic():
            save_point = transaction.savepoint()
            order = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )


            # 二, 再去实现订单商品列表的保存
            #     2.1 连接redis
            redis_conn = get_redis_connection('cart')
            #     2.2 获取redis的数据 hash,set
            sku_id_counts = redis_conn.hgetall('cart_%s'%user.id)
            selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)

            #     2.3 对redis数据进行转换,
            #             在转换过程中只转换 选中的信息
            #         {sku_id:count}
            redis_selected_cart = {}
            for sku_id in  selected_ids:
                redis_selected_cart[int(sku_id)]=int(sku_id_counts[sku_id])

            # redis_selected_cart = {sku_id:count,sku_id:count}
            #     2.4 对选中商品信息的列表进行遍历
            for sku_id,count in redis_selected_cart.items():
                while True:
                    #         2.5 根据商品id进行查询
                    try:
                        sku = SKU.objects.get(pk=sku_id)
                    except SKU.DoesNotExist:
                        # 回滚
                        transaction.savepoint_rollback(save_point)
                        # 订单下单失败
                        raise serializers.ValidationError('商品不存在')

                    #         2.6 查询出来之后我们要根据商品的数量进行
                    if sku.stock < count:
                        transaction.savepoint_rollback(save_point)
                        # 库存不足
                        raise serializers.ValidationError('库存不足')

                    #             判断,库存是否充足
                    #         2.7 库存减少,销量增加

                    #模拟并发
                    # import time
                    # time.sleep(7)

                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()

                    #1. 先查询一个库存
                    old_stock = sku.stock
                    #2.计算更新之后的数据
                    new_stock = sku.stock-count #库存
                    new_sales = sku.sales+count #销量
                    #3.更新数据前 再次查询一下,看现在的数量是否和之前记录的一致,
                    # 一致则更新,不一致则不更新

                    # 如果更新成功则返回1
                    # 如果更新不成功则返回0
                    rect = SKU.objects.filter(pk=sku.id,stock=old_stock).update(stock=new_stock,sales=new_sales)

                    if rect == 0:
                        continue
                        # 表示下单失败,下单失败需要回滚,同时抛出异常
                        # transaction.savepoint_rollback(save_point)
                        # raise serializers.ValidationError('下单失败')

                    #         2.8 遍历的过程中 累加商品总数量和总价格
                    order.total_count += count
                    order.total_amount += (count*sku.price)

                    #         2.9 商品数据入库

                    OrderGoods.objects.create(
                       order=order,
                        sku=sku,
                        count=count,
                        price=sku.price
                    )

                    break

            # 都遍历完成之后,我们只写入数据一次
            order.save()
            transaction.savepoint_commit(save_point)
            # 清除redis中选中商品的信息
            pl = redis_conn.pipeline()
            pl.hdel('cart_%s' % user.id, *selected_ids)
            pl.srem('cart_selected_%s' % user.id, *selected_ids)
            pl.execute()


            return order



        # redis_conn = get_redis_connection('cart')
        # sku_id_count = redis_conn.hgetall('cart_%s'%user.id)
        # selected_ids = redis_conn.smembers('cart_selected_%s'%user.id)
        # redis_selected_cart = {}
        # for sku_id in selected_ids:
        #     redis_selected_cart[int(sku_id)]=int(sku_id_count[sku_id])


#订单商品查询数据
class OrderSKUSerializer(serializers.ModelSerializer):
    """
    订单商品查询数据
    """
    class Meta:
        model = SKU
        fields = ('id', 'name', 'default_image_url')


class OrderListSKUSerializer(serializers.ModelSerializer):

    sku = OrderSKUSerializer()

    class Meta:
        model = OrderGoods
        fields = '__all__'


class OrderListSerializer(serializers.ModelSerializer):

    # OrderGoods中 order关系字段 related_name='skus'
    skus = OrderListSKUSerializer(many=True)

    class Meta:
        model = OrderInfo
        exclude = ['update_time', 'address', 'user']
        extra_kwargs = {
            'create_time':{
                'format': '%Y年%m月%d日 %H:%M:%S',
            },
        }


class CommentOrderSerializer(serializers.ModelSerializer):

    comment = serializers.CharField(min_length=5, required=True)
    score = serializers.IntegerField(min_value=0, max_value=5, required=True)
    is_anonymous = serializers.BooleanField(required=True)

    class Meta:
        model = OrderGoods
        fields = ['order_id', 'sku_id', 'comment', 'score', 'is_anonymous']

    def update(self, instance, validated_data):
        """
        保存订单信息, 修改订单状态
        """

        instance = super().update(instance, validated_data)
        instance.is_commented = True
        instance.user = self.context['request'].user
        instance.save()

        return instance